package com.atguigu.proxy;

import com.atguigu.interf.Calculator;
import com.atguigu.utils.LogUtils;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * 帮Calculator.java 生成代理对象的类
 *      Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler)
 * @author 伟哥
 * @date 2021-05-01 9:59
 */
public class CalculatorProxyLog {

    public static Calculator getProxy(final Calculator calculator){

        //目标对象的，类加载器
        ClassLoader loader = calculator.getClass().getClassLoader();
        //目标对象，实现的方法
        Class<?>[] interfaces = calculator.getClass().getInterfaces();

        //方法执行器：帮助目标对象，执行方法
        InvocationHandler handler = new InvocationHandler() {
            /**
             *
             * @param proxy 目标对象：给JDK使用，任何时候都不要动这个对象
             * @param method 当前将要执行的，目标对象的方法
             * @param args 这个方法调用时，外界传入的参数值
             * @return 方法调用的结果
             * @throws Throwable
             */
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

                /**
                 * 利用反射，执行目标方法
                 * 参数：object  执行方法的对象，此处我们代理的是calculator
                 *              当前方法是内部类，而需要的参数calculator，在外部，需要给外部参数加上final修饰
                 *              内部类，才能引用外部的参数
                 *      args  代理对象calculator的参数
                 */
                //System.out.println("这是jdk动态代理将要帮你执行方法...");
                Object result = null;
                try {
                    LogUtils.logStart(method,args);

                    result = method.invoke(calculator, args);
                    LogUtils.logEnd(result);
                } catch (Exception e) {
                    LogUtils.logException(e);
                } finally {
                    LogUtils.logFinal(method);
                }
                return result;
            }
        };

        Calculator proxyInstance = (Calculator)Proxy.newProxyInstance(loader, interfaces, handler);
        return proxyInstance;
    }

}
